package wx

import (
	"crypto/rand"
	"crypto/sha1"
	"fmt"
	"log"
	"math/big"
	"sort"
	"strconv"
	"strings"
	"time"

	"gin.andbridge/core/dao"
	"gin.andbridge/core/model"
	"github.com/go-resty/resty/v2"
)

type Wx struct{}

func (wx *Wx) getAccessToken() *model.AccessToken {
	client := resty.New()
	const appid = "appid"
	const appsecret = "密钥"
	url := fmt.Sprintf("https://api.weixin.qq.com/cgi-bin/token?grant_type=client_credential&appid=%s&secret=%s", appid, appsecret)
	response, err := client.R().SetResult(&model.AccessToken{}).Get(url)
	if err != nil {
		log.Panicf("accessToken请求错误%v", err)
	}

	return response.Result().(*model.AccessToken)
}

func (wx *Wx) getTicket(AccessToken *model.AccessToken) *model.Ticket {
	client := resty.New()
	url := fmt.Sprintf("https://api.weixin.qq.com/cgi-bin/ticket/getticket?access_token=%s&type=jsapi", AccessToken.AccessToken)
	response, err := client.R().SetResult(&model.Ticket{}).Get(url)
	if err != nil {
		log.Panicf("ticket请求错误%v", err)
	}
	return response.Result().(*model.Ticket)
}
func (wx *Wx) createNonceStr() string {

	r, err := rand.Int(rand.Reader, big.NewInt(1000000))

	if err != nil {
		log.Panicf("随机字符串生成失败%v", err)
	}

	return fmt.Sprintf("%s", strconv.FormatInt(r.Int64(), 2))
}

func (wx *Wx) createTimestamp() int64 {

	return time.Now().Unix() / 5
}

func (wx *Wx) organizeSourceString(Ticket *model.Ticket, nonceStr string, timestamp int64) string {
	obj := map[string]interface{}{
		"nonceStr":     nonceStr,
		"timestamp":    timestamp,
		"url":          "https://zhiantong.0570.net/entry.html",
		"jsapi_ticket": Ticket.Ticket,
	}
	objKey := []string{}
	for k, _ := range obj {
		objKey = append(objKey, k)
	}
	sort.Strings(objKey)
	sourceString := ""
	for _, v := range objKey {
		sourceString = fmt.Sprintf("%s%s=%v&", sourceString, strings.ToLower(v), obj[v])
	}

	return sourceString[:len([]rune(sourceString))-1]
}

func (wx *Wx) SignJSSDK() *model.JSSDKSign {
	nonceStr := wx.createNonceStr()
	timestamp := wx.createTimestamp()
	WxAccessTokenAndTicket, err := dao.Export.LookupWxAccessTokenAndTicket()
	var AccessToken *model.AccessToken
	var Ticket *model.Ticket
	if err != nil {
		AccessToken = wx.getAccessToken()
		Ticket = wx.getTicket(AccessToken)
		dao.Export.StoreWxAccessTokenAndTicket(&model.WxAccessTokenAndTicket{
			AccessToken: AccessToken,
			Ticket:      Ticket,
		}, time.Second*7000)
		log.Printf("dao获取wxAccessTokenAndTicket数据失败：%v", err)
	} else {
		AccessToken = WxAccessTokenAndTicket.AccessToken
		Ticket = WxAccessTokenAndTicket.Ticket
	}

	sourceString := wx.organizeSourceString(Ticket, nonceStr, timestamp)
	signature := sha1.Sum([]byte(sourceString))
	return &model.JSSDKSign{
		Noncestr:  nonceStr,
		Timestamp: timestamp,
		Signature: fmt.Sprintf("%x", signature),
	}
}
